<!DOCTYPE html>
<html lang="zh_cn">
<head>
          <title>来玩魔王的咚</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="utf-8" />
        <!-- twitter card metadata -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/images/mowang.png">
<meta name="twitter:site" content="">
<meta name="twitter:title" content="pytest（三）参数化测试">
<meta name="twitter:description" content="<p>使用pytest进行参数化测试。</p>">
        <!-- OG Tags -->
<meta property="og:url" content="/pytest-parametrize.html"/>
<meta property="og:title" content="来玩魔王的咚 | pytest（三）参数化测试" />
<meta property="og:description" content="<p>使用pytest进行参数化测试。</p>" />
        <!-- favicon -->
        <link rel="icon" type="image/png" href="/images/mowang.png">
        <!-- moment.js for date formatting -->
        <script src="/theme/js/moment.js"></script>
        <!-- css -->
        <link rel="stylesheet" type="text/css" href="/theme/css/main.css" />
        <!-- 左边的menu，如果页面高度不够，就跟着滚动，否则文章分类显示不全 -->
        <link rel="stylesheet" type="text/css" href="/theme/css/mycss/menu.css" />
		<script>
			
                /*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
    
    (function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
                
                grunticon(["/theme/css/icons.data.svg.css", "/theme/css/icons.data.png.css", "/theme/css/icons.fallback.css"]);
            </script>
        <noscript><link href="/theme/css/icons.fallback.css" rel="stylesheet"></noscript>
        <!-- menu toggle javascript -->
        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", initMenu);
            
            function initMenu(){
                var menu = document.getElementById("menu");
                var menulink = document.getElementById("menu-link");
                menulink.addEventListener("click", function toggleMenu(){
                        window.event.preventDefault();
                        menulink.classList.toggle('active');
                        menu.classList.toggle('active');              
                    });
            };
        </script>
        <!-- 不蒜子 -->
        <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    <meta name="description" content="<p>使用pytest进行参数化测试。</p>" />

    <meta name="tags" content="测试" />
  <!-- 替换部分base的样式，看文章时，要再宽一点，右边有很多空间可以撑开 -->
  <link rel="stylesheet" type="text/css" href="/theme/css/mycss/article.css" />

</head>
<body>
    <div role="banner" id="masthead">
        <header>
            <a href="/"><img src="/images/mowang.png" alt="McManus Logo"></a>
                <h1>来玩魔王的咚@骑士救兵</h1>
            <a href="#menu" id="menu-link">more stuff</a>
            <nav id="menu">
                <ul>
                        <li><a href="/tags">tags</a></li>
                            <li><a href="/category/cloud.html">Cloud</a></li>
                            <li><a href="/category/docker.html">Docker</a></li>
                            <li><a href="/category/go.html">Go</a></li>
                            <li><a href="/category/linux.html">Linux</a></li>
                            <li class="active"><a href="/category/python.html">Python</a></li>
                            <li><a href="/category/xue-xi-bi-ji.html">学习笔记</a></li>
                            <li><a href="/category/yun-wei-zi-dong-hua.html">运维自动化</a></li>
                </ul>
            </nav>
        </header>
    </div>
        <div class="page" role="main">
  <div class="article" role="article">
    <article>
        <footer>
            <a name="top"></a>
            <p>
              <time datetime=" 2022-03-21 14:41:00+08:00">
                <script>document.write(moment('2022-03-21 14:41:00+08:00').format('LL'));</script>
              </time>
              ~
              <time datetime=" 2022-03-21 14:41:00+08:00">
                <script>document.write(moment('2022-03-21 16:10:00+08:00').format('LL'));</script>
              </time>
            </p>
        </footer>
        <header>
          <h2>
            pytest（三）参数化测试
          </h2>
        </header>
      <div class="content">
         <div class="toc">
<ul>
<li><a href="#ce-shi-han-shu-can-shu-hua">测试函数参数化</a></li>
<li><a href="#zai-lei-shang-can-shu-hua">在类上参数化</a></li>
<li><a href="#mo-kuai-ji-bie-can-shu-hua">模块级别参数化</a></li>
<li><a href="#pytestparam">pytest.param()</a></li>
<li><a href="#duo-zu-can-shu-hua">多组参数化</a><ul>
<li><a href="#he-gu-jian-can-shu-hua-zu-he">和固件参数化组合</a></li>
</ul>
</li>
<li><a href="#ming-ling-xing-can-shu-can-shu-hua">命令行参数参数化</a></li>
</ul>
</div>
<p>pytest有以下的方式可以实现测试的参数化：</p>
<ul>
<li>固件参数化，查看<a href="/pytest-fixture.html#parametrizing-fixtures-can-shu-hua-gu-jian">参数化固件</a>那篇</li>
<li>测试函数参数化，本篇重点</li>
<li>命令行参数参数化，也是本篇讲</li>
</ul>
<h3 id="ce-shi-han-shu-can-shu-hua"><a class="toclink" href="#ce-shi-han-shu-can-shu-hua">测试函数参数化</a></h3>
<p>使用内置的<code>@pytest.mark.parametrize</code>装饰器，可以对测试函数的参数参数化。<br>
这是一个典型的示例，传入输入和预期的输出，在测试函数内就行测试：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;test_input,expected&quot;</span><span class="p">,</span> <span class="p">[(</span><span class="s2">&quot;3+5&quot;</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="p">(</span><span class="s2">&quot;2+4&quot;</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span> <span class="p">(</span><span class="s2">&quot;6*7&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">test_eval</span><span class="p">(</span><span class="n">test_input</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="nb">eval</span><span class="p">(</span><span class="n">test_input</span><span class="p">)</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div>

<p>装饰器的第一个参数是测试函数的参数名称的列表，逗号分隔的字符串格式。也可以是以字符串为元素组成的列表或元组。<br>
第二个参数是每一组的参数值组成的列表。列表内是元祖，元祖的元素一次对应位置参数的位置。  </p>
<p><strong>注意</strong>：参数会直接传给测试函数。如果是复合型的数据比如列表、字典，测试函数可以修改数据，修改的就是原值。这些修改会影响之后的其他测试。  </p>
<h3 id="zai-lei-shang-can-shu-hua"><a class="toclink" href="#zai-lei-shang-can-shu-hua">在类上参数化</a></h3>
<p>可以把装饰器直接装饰在类上：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;n,expected&quot;</span><span class="p">,</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)])</span>
<span class="k">class</span> <span class="nc">TestClass</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">test_simple_case</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>

    <span class="k">def</span> <span class="nf">test_weird_simple_case</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
        <span class="k">assert</span> <span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div>

<h3 id="mo-kuai-ji-bie-can-shu-hua"><a class="toclink" href="#mo-kuai-ji-bie-can-shu-hua">模块级别参数化</a></h3>
<p>模块上无法加装饰器，用下面的方式实现参数化：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="n">pytestmark</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;n,expected&quot;</span><span class="p">,</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)])</span>

<span class="k">def</span> <span class="nf">test_simple_case</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>

<span class="k">def</span> <span class="nf">test_weird_simple_case</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>

<span class="k">class</span> <span class="nc">TestClass</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">test_simple_case</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
        <span class="k">assert</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>

    <span class="k">def</span> <span class="nf">test_weird_simple_case</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
        <span class="k">assert</span> <span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div>

<p>模块级别设置的参数化，对模块内所有的测试函数，以及在测试类中的测试方法都有效。  </p>
<h3 id="pytestparam"><a class="toclink" href="#pytestparam">pytest.param()</a></h3>
<p>使用<code>pytest.param()</code>，不仅能传值，还能为每组测试参数加上id和mark：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span>
    <span class="s2">&quot;test_input,expected&quot;</span><span class="p">,</span> 
    <span class="p">[(</span><span class="s2">&quot;3+5&quot;</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="p">(</span><span class="s2">&quot;2+4&quot;</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span> <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span><span class="s2">&quot;6*7&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">,</span> <span class="n">marks</span><span class="o">=</span><span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">)]</span>
<span class="p">)</span>
<span class="k">def</span> <span class="nf">test_eval</span><span class="p">(</span><span class="n">test_input</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="nb">eval</span><span class="p">(</span><span class="n">test_input</span><span class="p">)</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div>

<p>也就是说最初的例子是简写，所有的参数都可以用<code>pytest.param()</code>传入完整的带id和mark的参数：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;test_input,expected&quot;</span><span class="p">,</span> <span class="p">[</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span><span class="s2">&quot;3+5&quot;</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;3 + 5&#39;</span><span class="p">),</span> 
    <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span><span class="s2">&quot;2+4&quot;</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;2 + 4&#39;</span><span class="p">),</span> 
    <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span><span class="s2">&quot;6*7&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">,</span> <span class="nb">id</span><span class="o">=</span><span class="s1">&#39;6 * 7&#39;</span><span class="p">,</span> <span class="n">marks</span><span class="o">=</span><span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">test_eval</span><span class="p">(</span><span class="n">test_input</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="nb">eval</span><span class="p">(</span><span class="n">test_input</span><span class="p">)</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div>

<h3 id="duo-zu-can-shu-hua"><a class="toclink" href="#duo-zu-can-shu-hua">多组参数化</a></h3>
<p>如果每一个参数都是独立的一些可选值，可以叠加多个参数化装饰器，测试所有的组合。<br>
下面的示例一共会生成6个参数化测试：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">])</span>
<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">,</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">test_foo</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
    <span class="k">pass</span>
</code></pre></div>

<h4 id="he-gu-jian-can-shu-hua-zu-he"><a class="toclink" href="#he-gu-jian-can-shu-hua-zu-he">和固件参数化组合</a></h4>
<p>可以给固件参数化，那么每个引用这个固件的测试，会对每个参数执行一次完整的测试。<br>
也能给测试本身做参数化。如果固件和测试都做了参数化，那么测试的数量会成倍的增长。固件有m个参数化数据，测试有n个参数化数据，会生成m*n个测试。<br>
下面的示例一共会生成6个参数化测试：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">params</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;Adam&quot;</span><span class="p">,</span> <span class="s2">&quot;Bob&quot;</span><span class="p">,</span> <span class="s2">&quot;Cara&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">last_name</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">request</span><span class="o">.</span><span class="n">param</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s1">&#39;first_name&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;Davis&#39;</span><span class="p">,</span> <span class="s1">&#39;Smith&#39;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">test_string</span><span class="p">(</span><span class="n">last_name</span><span class="p">,</span> <span class="n">first_name</span><span class="p">):</span>
    <span class="k">pass</span>
</code></pre></div>

<h3 id="ming-ling-xing-can-shu-can-shu-hua"><a class="toclink" href="#ming-ling-xing-can-shu-can-shu-hua">命令行参数参数化</a></h3>
<p>通过命令行参数的方式提供测试的参数。定义命令行参数让pytest可以捕获命令行中指定的参数值。再通过<code>metafunc.parametrize()</code>实现参数化。这些步骤都设置在<code>conftest.py</code>中：</p>
<div class="highlight"><pre><span></span><code><span class="c1"># content of conftest.py</span>
<span class="k">def</span> <span class="nf">pytest_addoption</span><span class="p">(</span><span class="n">parser</span><span class="p">):</span>
    <span class="n">parser</span><span class="o">.</span><span class="n">addoption</span><span class="p">(</span>
        <span class="s2">&quot;--stringinput&quot;</span><span class="p">,</span>
        <span class="n">action</span><span class="o">=</span><span class="s2">&quot;append&quot;</span><span class="p">,</span>
        <span class="n">default</span><span class="o">=</span><span class="p">[],</span>
        <span class="n">help</span><span class="o">=</span><span class="s2">&quot;list of stringinputs to pass to test functions&quot;</span><span class="p">,</span>
    <span class="p">)</span>

<span class="k">def</span> <span class="nf">pytest_generate_tests</span><span class="p">(</span><span class="n">metafunc</span><span class="p">):</span>
    <span class="k">if</span> <span class="s2">&quot;stringinput&quot;</span> <span class="ow">in</span> <span class="n">metafunc</span><span class="o">.</span><span class="n">fixturenames</span><span class="p">:</span>
        <span class="n">metafunc</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s2">&quot;stringinput&quot;</span><span class="p">,</span> <span class="n">metafunc</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">getoption</span><span class="p">(</span><span class="s2">&quot;stringinput&quot;</span><span class="p">))</span>


<span class="c1"># content of test_strings.py</span>
<span class="k">def</span> <span class="nf">test_valid_string</span><span class="p">(</span><span class="n">stringinput</span><span class="p">):</span>
    <span class="k">assert</span> <span class="n">stringinput</span><span class="o">.</span><span class="n">isalpha</span><span class="p">()</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="kn">import</span> <span class="nn">pytest</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">main</span><span class="p">([</span><span class="vm">__file__</span><span class="p">,</span> <span class="s1">&#39;--stringinput&#39;</span><span class="p">,</span> <span class="s1">&#39;hello&#39;</span><span class="p">,</span> <span class="s1">&#39;--stringinput=world&#39;</span><span class="p">])</span>
</code></pre></div>

<p>测试函数中直接使用自定义的参数的名称即可。  </p>
<p>这种情况必须要通过命令行参数才能提供测试值，如果未提供自定义的命令行参数，测试结果是一个skipped的标记。  </p>
      </div>
      <div class="back-to-top">
        <a href="/">HOME</a>
        <a href="#top">TOP</a>
      </div>
    </article>
  </div>
<!-- end article -->
<!-- 页面往下滚动一段之后才会显示TOC -->
<script>
  window.onscroll = function() {
    var tocbox = document.getElementsByClassName('toc')[0];
    var osTop = document.documentElement.scrollTop || document.body.scrollTop;
    var osWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
    // console.log(osTop)
    if (osTop>300 && osWidth>865) {
      tocbox.style.display = "block"
    }
    if (osTop<300 || osWidth<865) {
      tocbox.style.display = "none"
    }
  }
</script>
                <footer>
                    <div class="icons">
                    </div>
                    <span id="busuanzi_container_page_pv" style="padding: 10px">本文阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                    <span id="busuanzi_container_site_pv" style="padding: 10px">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
                    <span id="busuanzi_container_site_uv" style="padding: 10px">本站总访客数<span id="busuanzi_value_site_uv"></span>人</span>
                    <p>© <script>document.write(moment().format('YYYY'));</script> 749B</p>
                </footer>
        </div>
</body>
</html>